package myJs.common

import com.softwaremill.quicklens._
import myJs.{CpLayer, MyPages}
import myJs.Implicits._
import myJs.api.Api
import myJs.common.{FormGroupInlineCp, PureDateTimePickerCp, PureInputCp, PureTextareaCp, TextareaInlineCp}
import myJs.cps.{AppendSelectCp, Style}
import myJs.myPkg.jquery.$
import myJs.myPkg.reactHookForm._
import myJs.myPkg.{ReactRouterDOM, SwalOptions, layer, swal}
import myJs.tool.Tool
import org.scalajs.dom.{File, FormData, URLSearchParams, html}
import org.scalajs.macrotaskexecutor.MacrotaskExecutor.Implicits._
import shared.pojo.Sample.ProcessData
import shared.pojo.Test.TestInfoData
import slinky.core.FunctionalComponent
import slinky.core.annotations.react
import slinky.core.facade.Hooks.{useEffect, useState}
import slinky.core.facade.React
import slinky.web.html._
import upickle.default._

import scala.scalajs.js
import scala.scalajs.js.{Date, JSON}
import typings.csstype.csstypeStrings

/**
 * Created by yz on 21/1/2022
 */
@react object UpdateTestFormCp {

  case class Props(testManagePage: MyPages)

  val component = FunctionalComponent[Props] { props =>
    val location = ReactRouterDOM.useLocation()
    val searchParams = new URLSearchParams(location.search)
    val curId = searchParams.get("id")
    val (idV, setIdV) = useState(curId)
    val initSampleInfo = TestInfoData(id = idV.toInt, info = List.empty[ProcessData])
    val (testData, setTestData) = useState(initSampleInfo)
    val (filess, setFiless) = useState(List[List[File]]())
    val useForm = ReactHookForm.useForm(UseFormOptions(mode = "onChange"))
    val navigate = ReactRouterDOM.useNavigate()

    val useFieldArray = ReactHookForm.useFieldArray(UseFieldArrayOptions(
      control = useForm.control,
      name = "info"
    ))

    object FTool {

      def initProcessData = {
        val time = Tool.formatDateTime(new Date())
        ProcessData(time = time)
      }

      def sampleIdChange = (v: String) => {
        val curTestData = testData.modify(_.sampleId).setTo(v)
        setTestData(curTestData)
      }

      def update = () => {
        val index = layer.alert(Tool.myElement, Tool.layerOptions)
        val formData = new FormData()
        filess.zipWithIndex.foreach { case (files, curI) =>
          files.foreach { file =>
            formData.append(s"${curI}", file)
          }
        }
        formData.append("testData", write(testData))
        Api.test.updateWorkflow(formData) { response =>
          layer.close(index)
          swal(SwalOptions(title = "成功", text = "更新成功!", `type` = "success"))
          navigate(s"${props.testManagePage.absolutePath}")
        }
        ()
      }

      def formSubmit = useForm.handleSubmit((data: js.Dictionary[js.Any]) => {
        println(JSON.stringify(data))
        FTool.update()
      })

      def insertProcess(curI: Int) = () => {
        val newSampleInfo = testData.modify(_.info).using { processes =>
          processes.insert(curI, FTool.initProcessData)
        }
        val newFiless = filess.insert(curI, List.empty)
        setFiless(newFiless)
        setTestData(newSampleInfo)
        useFieldArray.insert(curI, FTool.initProcessData)
      }

      def removeProcess(curI: Int) = () => {
        val newSampleInfo = testData.modify(_.info).using { processes =>
          processes.removedByI(curI)
        }
        val newFiless = filess.removedByI(curI)
        setFiless(newFiless)
        setTestData(newSampleInfo)
        useFieldArray.remove(curI)
      }

      def titleChange(curI: Int) = (v: String) => {
        setTestData(testData.modify(_.info).using { workflow =>
          val newData = workflow(curI).modify(_.title).setTo(v)
          workflow.updated(curI, newData)
        })
      }

      def timeChange(curI: Int) = (v: String) => {
        setTestData(testData.modify(_.info).using { workflow =>
          val newData = workflow(curI).modify(_.time).setTo(v)
          workflow.updated(curI, newData)
        })
      }

      def contentChange(curI: Int) = (v: String) => {
        val curTestData = testData.modify(_.info).using { processes =>
          processes.modify(_.index(curI)).using { process =>
            process.modify(_.content).setTo(v)
          }
        }
        setTestData(curTestData)
      }

      def filesChange(curI: Int) = (vs: List[File]) => {
        val newFiless = filess.updated(curI, vs)
        setFiless(newFiless)
      }

      def serverFilesChange(curI: Int) = (vs: List[String]) => {
        val newSampleInfo = testData.modify(_.info).using { workflows =>
          val newWorkflowData = workflows(curI).modify(_.fileNames).setTo(vs)
          val newWorkflows = workflows.updated(curI, newWorkflowData)
          newWorkflows
        }
        setTestData(newSampleInfo)
      }

      def addProcess = () => {
        val newSampleInfo = testData.modify(_.info).using { processes =>
          val newProcess = FTool.initProcessData
          val newWorkflows = processes :+ newProcess
          newWorkflows
        }
        val newFiless = filess :+ List.empty
        setFiless(newFiless)
        setTestData(newSampleInfo)
        useFieldArray.append(FTool.initProcessData)
      }

      def refreshData = {
        Api.test.getById(idV).map { curTestData =>
          val newFiless = curTestData.info.map(x => List.empty[File])
          setFiless(newFiless)
          setTestData(curTestData)
          useForm.reset(curTestData)
        }

      }

    }

    useEffect(() => {
      FTool.refreshData
    }, List()
    )

    form(className := "form-horizontal", onSubmit := FTool.formSubmit,

      div(className := "form-group",
        label(className := "control-label col-sm-2", "样本编号:"),
        div(className := "col-sm-4",
          PureInputCp(useForm = useForm, name = "sampleId", `type` = "text", value = testData.sampleId,
            onChange = FTool.sampleIdChange,
            readOnly = true)
        )
      ),

      div(className := "form-group",
        label(className := "control-label col-sm-2", "测试类型:"),
        div(className := "col-sm-4",
          PureInputCp(useForm = useForm, name = "testType", `type` = "text", value = testData.testType,
            onChange = FTool.sampleIdChange,
            readOnly = true)
        )
      ),

      h4("流程"),

      useFieldArray.fields.toList.zipWithIndex.map { case (item, curI) =>
        val files = filess(curI)
        val processData = testData.info(curI)
        div(key := s"${item.id}",
          div(style := Style(paddingRight = "5px", border = "1px solid silver", margin = "0 2px",
            background = "#f8f8fa", borderRadius = "4px"),
            className := "northbtn myEachSoft",

            div(style := Style(display = csstypeStrings.flex, justifyContent = csstypeStrings.`flex-end`), className := "myTool",
              span(style := Style(cursor = csstypeStrings.pointer, marginRight = 3), title := "插入",
                className := "myInsertSoftShow", onClick := FTool.insertProcess(curI),
                i(className := "fa fa-plus-square")),
              span(style := Style(cursor = csstypeStrings.pointer), title := "删除", className := "myRemoveSoft",
                onClick := FTool.removeProcess(curI),
                i(className := "fa fa-remove"))
            ),

            FormGroupInlineCp(useForm = useForm, names = List(s"info.${curI}.title"))(
              label(className := "control-label col-sm-2", "时间:"),
              div(className := "col-sm-3",
                PureDateTimePickerCp(useForm = useForm, name = s"info.${curI}.time", value = processData.time,
                  onChangeF = FTool.timeChange(curI))
              ),
              label(className := "control-label col-sm-2", "标题:"),
              div(className := "col-sm-3",
                PureInputCp(useForm = useForm, name = s"info.${curI}.title", `type` = "text", value = processData.title,
                  onChange = FTool.titleChange(curI), registerOptions = RegisterOptions(
                    required = ValidationValueMessage(value = true, message = "标题不能为空！")
                  ))
              )
            ),

            TextareaInlineCp(useForm = useForm, label = "内容", name = s"info.${curI}.content", labelWidth = 2, inputWidth = 8,
              value = processData.content,
              onChange = FTool.contentChange(curI), registerOptions = RegisterOptions(
                required = ValidationValueMessage(value = true, message = "内容不能为空！")
              )),

            div(className := "form-group",
              label(className := "control-label col-sm-2", "附件:"),
              div(className := "col-sm-8",
                AppendSelectCp(files = files, filesChange = FTool.filesChange(curI),
                  serverFiles = processData.fileNames.toList, serverFilesChange = FTool.serverFilesChange(curI),
                  folder = processData.folder, id = testData.sampleId, testId = testData.id)
              )
            ),
          ),
          {
            if (curI < testData.info.size - 1) {
              div(style := Style(textAlign = csstypeStrings.center, marginTop = 10, marginBottom = 10,
                fontSize = 16),
                className := "myArrow",
                i(className := "fa fa-angle-double-down")
              )
            } else null
          }
        )

      },

      div(style := Style(marginTop = 10), className := "form-group",
        div(className := "actions col-sm-offset-2 col-sm-6",
          button(`type` := "button", className := "btn btn-default", onClick := FTool.addProcess, "新增过程")
        )
      ),

      div(className := "form-group",
        div(className := "actions col-sm-offset-2 col-sm-2",
          button(`type` := "submit", className := "btn btn-primary myAddShow",
            s" 更新",
          ),
        )
      ),

    )


  }


}
